package main

import (
	"fmt"
)

type ProcessData struct {
	processName   string  // 进程名称
	arriveTime    int     // 到达时间
	startTime     int     // 开始时间
	finishTime    int     // 结束时间
	turnTime      int     // 周转时间
	workTime      int     // 总工作时间
	workedTime    int     // 已工作时间
	powerTime     float64 // 带权周转时间
	responseTime  int     // 响应时间
	processStatus int     // 进程状态
	flag          bool    // 标志第一次运行
}

const (
	takein = iota
	run
	end
)

var (
	currentTime = 0 // 当前时间
	cpuTime     = 4 // 时间片大小
	finished    = 0 // 已完成进程
)

func main() {
	// 初始化队列
	pcds := make([]ProcessData, 5)
	// 加入队列进程
	pcds[0] = ProcessData{
		processName:   "A",
		arriveTime:    0,
		workTime:      4,
		processStatus: takein,
	}
	pcds[1] = ProcessData{
		processName:   "B",
		arriveTime:    1,
		workTime:      3,
		processStatus: takein,
	}
	pcds[2] = ProcessData{
		processName:   "C",
		arriveTime:    2,
		workTime:      4,
		processStatus: takein,
	}
	pcds[3] = ProcessData{
		processName:   "D",
		arriveTime:    3,
		workTime:      2,
		processStatus: takein,
	}
	pcds[4] = ProcessData{
		processName:   "E",
		arriveTime:    4,
		workTime:      4,
		processStatus: takein,
	}
	// 运行轮转算法
	startProcess(pcds)
	// 计算平均值
	calcAvg(pcds)
}

// 格式化显示进程数据
func Display(pcds []ProcessData) {
	fmt.Printf("当前时间为: %d时, 各进程的信息:\n", currentTime)
	fmt.Printf("%-5s%-6s%-6s%-6s%-6s%-7s%-7s%-8s%-6s%-6s\n",
		"进程名",
		"到达时间",
		"开始时间",
		"结束时间",
		"周转时间",
		"总工作时间",
		"已工作时间",
		"带权周转时间",
		"响应时间",
		"状态")
	// 遍历显示进程数据
	for _, p := range pcds {
		fmt.Printf("%-8s%-10d%-10d%-10d%-10d%-12d%-12d%-14.2f%-10d%-8d\n",
			p.processName,
			p.arriveTime,
			p.startTime,
			p.finishTime,
			p.turnTime,
			p.workTime,
			p.workedTime,
			p.powerTime,
			p.responseTime,
			p.processStatus,
		)
	}
}

// 轮转算法
func startProcess(pcds []ProcessData) {
	// 循环至每个程序结束
	for finished < len(pcds) {
		// 判断进程是否到达以及是否完成
		if pcds[0].arriveTime <= currentTime && pcds[0].processStatus != end {
			// 运行时间片
			runProcess(&pcds[0])
			Display(pcds)
		}
		// 将当前进程切换至队末
		copy(pcds, append(pcds[1:], pcds[0]))
	}
}

// 运行时间片
func runProcess(pcd *ProcessData) {
	// 记录开始时间
	if !pcd.flag {
		pcd.startTime = currentTime
		pcd.responseTime = pcd.startTime - pcd.arriveTime
		pcd.processStatus = run
		pcd.flag = !pcd.flag
	}
	// 遍历时间片
	for i := 0; i < cpuTime; i++ {
		currentTime++
		pcd.workedTime++
		// 判断程序是否结束
		if pcd.workedTime >= pcd.workTime {
			pcd.finishTime = currentTime
			pcd.turnTime = pcd.finishTime - pcd.arriveTime
			pcd.powerTime = float64(pcd.turnTime) / float64(pcd.workTime)
			pcd.processStatus = end
			// 记录已完成进程数目
			finished++
			return
		}
	}
}

// 计算平均值
func calcAvg(pcds []ProcessData) {
	var totalTurn float64
	var totalPower float64
	var totalResp float64
	for _, p := range pcds {
		totalTurn += float64(p.turnTime)
		totalPower += p.powerTime
		totalResp += float64(p.responseTime)
	}
	fmt.Println("平均周转时间:", totalTurn/float64(len(pcds)))
	fmt.Println("平均带权周转时间:", totalPower/float64(len(pcds)))
	fmt.Println("平均响应时间:", totalResp/float64(len(pcds)))
}
